/**
 * Task Calculator for Google Calendar
 *
 * Copyright (C) 2007 Firma JAKUBIAK Antoni Jakubiak
 * http://www.jakubiak.biz/
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

/**
 * Create task from GData entry
 * @param entry GData
 */ 
function Task(entry) {
	this.title = entry.title.$t;
	this.start = this._parseDate(entry['gd$when'][0].startTime);
	this.end   = this._parseDate(entry['gd$when'][0].endTime);
	this.time  = new Date();
	if(this.end) {
		this.time.setTime(this.end.getTime() - this.start.getTime());
	} else {
		this.time.setTime(0);
	}
}		
 
/**
 * Parse date
 * @private 
 */
Task.prototype._parseDate = function dateString(dateString) {
	var re = /(\d\d\d\d)-(\d\d)-(\d\d)T(\d\d):(\d\d)/; // T(\d\d:\d\d)");
	if(!re.test(dateString)) return null;
	var m = re.exec(dateString);
	return new Date( Date.UTC(m[1], m[2] - 1, m[3], m[4], m[5], 0) );
}




/**
 * Create report
 * @param iRegExp math to title
 * @param iStartMin date have to be after this
 * @param iStartMax date have to be before this
 */
function Report(iRegExp,iStartMin,iStartMax) {
	this.regExp = iRegExp;
	this.startMin = iStartMin;
	this.startMax = iStartMax;
	this.minDate  = null;
	this.maxDate  = null;
	this.sum	  = new Date(0);
	this.tasks    = new Array();
}

/**
 * Test if task match to this report
 * @param Task task
 * @return true if task match reporti criteria
 */
Report.prototype.test = function(task) {
	if(this.regExp&& ! this.regExp.test(task.title)) {
		// title of task does not pass search criteria
		return false;
	}
	if(this.startMin && this.startMin.getTime() > task.start.getTime()) {
		// task start befor startMin
		return false;
	}
	if(this.startMax && this.startMax.getTime() < task.start.getTime()) {
		// task start after startMax
		return false;
	}
	return true;
}

/**
 * If task pass to report criteria collect it
 * @param Array of Task iTasks
 */
Report.prototype.addAll = function(iTasks) {
	// report criteria
	for( var i in iTasks ) {
		if( this.test(iTasks[i]) ) {
			this.tasks.push( iTasks[i] );
		}
	}
	// report results
	for( var i in this.tasks ) {
		var task = this.tasks[i];
		this.sum.setTime( this.sum.getTime() + task.time.getTime() );
	}
}

/**
 * Return total time HH:MM
 */
Report.prototype.getSumHhmm = function() {
	var minutes = Math.round( this.sum.getTime() / (60 * 1000) );
	var hh = Math.floor(minutes/60)
	var mm = minutes % 60;
	return hh + ":" + (mm<10?"0":"")+mm;
}












/**
 * Constructor
 */ 
function TaskCalculator() {
	TaskCalculator.instance = this;
	this.tasks = new Array();
}

/**
 * JSON Callback
 */
function taskCalculatorCallback(root) {
	TaskCalculator.instance._onloadCallback(root);
}

/**
 * Set URL with private google calendar xml
 * @param iUrl
 */
TaskCalculator.prototype.setUrl = function(iUrl) {
	this.url = iUrl.replace(/basic$/, "full-noattendees");
}
/**
 * This method will be invoke after loading data from Google
 * Overwrite it!
 */ 
TaskCalculator.prototype.onload = function() {
}





/**
 * Create query to google, download data and parse it
 */
TaskCalculator.prototype.run = function() {
	var startMin="2006-01-01T00:00:00";
	var startMax="2008-12-31T23:59:59";
	var maxResults=300;
	var url = this.url + "?alt=json-in-script&callback=taskCalculatorCallback&orderby=starttime";
	url = url +"&start-min="+startMin;
	url = url +"&start-max="+startMax;
	url = url +"&max-results="+maxResults;
	this.tasks = new Array();
	this._load(url);
}




/**
 * Set extra tags to search
 * @param array iLabels
 */ 
TaskCalculator.prototype.setLabels = function(iLabels) {
	this.labels = iLabels;
}


/**
 * Podsumowanie
 */
TaskCalculator.prototype.getSumaryHtml = function() {
	return this._sumaryHtml;
}



/**
 * JavaScript Request
 * @private
 */
TaskCalculator.prototype._load = function(url) {
	var jsNode = document.createElement("script");
	jsNode.type = "text/javascript";
	jsNode.charset = "utf-8";
	jsNode.src = url;
	var headNode = document.getElementsByTagName("head").item(0);
	headNode.appendChild(jsNode);
}









/**
 * Parse calendar data
 */
TaskCalculator.prototype._onloadCallback = function(root) {
    var feed = root.feed;
    var entries = feed.entry || [];
    for (var i = 0; i < feed.entry.length; ++i) {
    	var entry = feed.entry[i];
    	var task = new Task(entry);
		this.tasks.push( task );
    }
    this.sumaryReport = new Report(null,null,null);
    this.sumaryReport.addAll( this.tasks ) ;
     
    this._sumaryHtml = "Total: " + this.sumaryReport.getSumHhmm();
    
    // TODO, test code
    for(var i in this.labels) {
    	var label = this.labels[i];
    	var report = new Report( new RegExp(label,"i"), null, null );
    	report.addAll( this.tasks );
    	this._sumaryHtml = this._sumaryHtml + "<br>" + label + ": " + report.getSumHhmm();
    }
    
    this.onload();
}


















 